#! /usr/bin/python

#manage item ranges, e.g. RSS read list

class Ranges:
	import re
	re_line1 = re.compile('(\d+)-(\d+)[\n]?')
	re_line2 = re.compile('(\d+)[\n]?')
	ranges = [()]
	def serialize(self,out_filename):
		out_file = open(out_filename, 'w+')
		if out_file==None: return
		for b,e in self.ranges:
			if b==e:
				out_file.write("%d\n"%b)
			else:
				out_file.write("%d-%d\n" % (b,e))
		out_file.close()

	def deserialize(self,in_filename):
		in_file = open(in_filename, 'r')
		if in_file==None: return
		self.ranges = []
		for line in in_file:
			m1 = self.re_line1.match(line)
			if m1!=None:
				beg = int(m1.group(1))
				end = int(m1.group(2))
				self.add_range(beg, end)
			else:
				m2 = self.re_line2.match(line)
				if m2!=None:
					beg = int(m2.group(1))
					self.add_range(beg, beg)
					#self.add_item(beg)
		in_file.close()

	def add_item(self,i):
		if len(self.ranges)==0:
			self.ranges.append((i,i))
			return
		for n,(beg,end) in enumerate(self.ranges):
			if i<beg:
				if i==beg-1: self.ranges[n]=(i, end)
				else: self.ranges.insert(n,(i,i))
				return
			elif beg<=i and i<=end:
				return
			elif i==end+1:
				self.ranges[n]=(beg,i)
				if n+1<len(self.ranges):
					bnext, enext = self.ranges[n+1]
					if bnext==i+1:
						self.ranges.pop(n)
						self.ranges[n] = (beg, enext)
				return
		self.ranges.append((i,i))

	def add_range(self,beg, end):
		if beg>end: return
		if len(self.ranges)==0:
			self.ranges.append((beg,end))
			return
		for n,(b,e) in enumerate(self.ranges):
			if beg<=e+1:
				beg = min(beg, b)
				self.ranges.insert(n, (beg,end))
				for b1,e1 in self.ranges[n+1:]:
					if end>=b1-1:
						end = max(end,e1)
						self.ranges.pop(n+1)
				self.ranges[n] = (beg,end)
				return
		self.ranges.append((beg,end))

	def rm_item(self,i):
		for n,(b,e) in enumerate(self.ranges):
			if b<=i<=e:
				self.ranges.pop(n)
				if i+1<=e: self.ranges.insert(n, (i+1,e))
				if b<=i-1: self.ranges.insert(n, (b,i-1))
				return

	def rm_range(self,beg, end):
		if beg>end: return
		n = 0
		while n<len(self.ranges):
			b,e = self.ranges[n]
			if beg<=e and end>=b:
				self.ranges.pop(n)
				if min(e,end)<e: self.ranges.insert(n, (min(e,end)+1,e))
				if b<max(b,beg): self.ranges.insert(n, (b,max(b,beg)-1))
				if end<=e: return
			else:
				n = n+1
	def item_in(self, i):
		for b,e in self.ranges:
			if b<=i<=e:
				return True
		return False

if __name__ == '__main__':
	r = Ranges()
	r.deserialize('fetched')
	r.add_range(19,21)
	print r.ranges
	r.rm_item(6)
	print 'r.rm_item(6)\t', r.ranges
	r.rm_item(1)
	print 'r.rm_item(1)\t', r.ranges
	r.rm_item(1)
	print 'r.rm_item(1)\t', r.ranges
	r.rm_item(9)
	print 'r.rm_item(9)\t', r.ranges
	r.rm_item(11)
	print 'r.rm_item(11)\t', r.ranges
	r.rm_range(12,23)
	print 'r.rm_range(12,23)\t', r.ranges
	r.add_item(6)
	print 'add_item(6)\t', r.ranges
	r.add_item(11)
	print 'add_item(11)\t', r.ranges
	r.add_item(19)
	print 'add_item(19)\t', r.ranges
	r.serialize('fetched2')
	r.deserialize('fetched2')
	print r.ranges

